package org.vaadinpa.gui.views;

import java.util.ArrayList;
import java.util.List;

import org.vaadinpa.data.Coordinate;
import org.vaadinpa.data.Fleet;
import org.vaadinpa.data.Fleet.FleetOrder;
import org.vaadinpa.data.Planet;
import org.vaadinpa.data.Ship;
import org.vaadinpa.data.Universe;
import org.vaadinpa.gui.VaadinPA;
import org.vaadinpa.gui.ViewWithCommands;
import org.vaadinpa.gui.util.NotificationUtil;
import org.vaadinpa.logic.Command;
import org.vaadinpa.logic.CommandHandler;
import org.vaadinpa.logic.commands.FleetMoveCommand;

import com.vaadin.data.Item;
import com.vaadin.ui.AbstractSelect;
import com.vaadin.ui.AbstractSelect.Filtering;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.Panel;
import com.vaadin.ui.Select;
import com.vaadin.ui.TextField;
import com.vaadin.ui.themes.Reindeer;

public class FleetView extends ViewWithCommands {

	private static final long serialVersionUID = -2947884665152314814L;

	private GridLayout ordersGrid = new GridLayout(2, 4);
	private OptionGroup fleetSelect = new OptionGroup();
	private OptionGroup orderSelect = new OptionGroup();
	private Select destinationSelect = new Select();

	private GridLayout compositionGrid = new GridLayout(4, 1);
	private TextField numField = new TextField("Move ships: ");
	private Select typeSelect = new Select();
	private AbstractSelect fromSelect = new OptionGroup();
	private AbstractSelect toSelect = new OptionGroup();

	public FleetView() {

		/* ORDERS */
		Label changeOrdersLabel = new Label("<b>Change current orders:</b> ", Label.CONTENT_XHTML);
		changeOrdersLabel.setSizeUndefined();

		fleetSelect.addContainerProperty("caption", String.class, "");
		fleetSelect.setItemCaptionPropertyId("caption");
		fleetSelect.setNullSelectionAllowed(false);
		for (Fleet f : VaadinPA.getPlanet().fleets) {
			Item i = fleetSelect.addItem(f);
			i.getItemProperty("caption").setValue(f.name);
		}
		fleetSelect.select(VaadinPA.getPlanet().fleets.get(0));
		// fleetSelect.setCaption("Fleet");

		orderSelect.addContainerProperty("caption", String.class, "");
		orderSelect.setItemCaptionPropertyId("caption");
		orderSelect.setNullSelectionAllowed(false);
		for (FleetOrder o : FleetOrder.values()) {
			Item i = orderSelect.addItem(o);
			i.getItemProperty("caption").setValue(o.toString());
		}
		orderSelect.select(FleetOrder.values()[0]);
		// orderSelect.setCaption("Order");

		destinationSelect.addContainerProperty("caption", String.class, "");
		destinationSelect.setItemCaptionPropertyId("caption");
		destinationSelect.setNullSelectionAllowed(false);
		destinationSelect.setCaption("Target");
		destinationSelect.setFilteringMode(Filtering.FILTERINGMODE_CONTAINS);

		Button send = new Button("Issue order", new OrderIssueListener());

		HorizontalLayout l = new HorizontalLayout();
		l.setSpacing(true);
		l.setWidth("600px");
		l.addComponent(changeOrdersLabel);
		l.addComponent(fleetSelect);
		l.addComponent(orderSelect);
		l.addComponent(destinationSelect);
		l.addComponent(send);
		l.setComponentAlignment(changeOrdersLabel, Alignment.MIDDLE_CENTER);
		l.setComponentAlignment(destinationSelect, Alignment.MIDDLE_CENTER);
		l.setComponentAlignment(send, Alignment.BOTTOM_CENTER);

		Panel ordersPanel = new Panel("Orders");
		ordersPanel.getContent().addStyleName(Reindeer.LAYOUT_BLACK);
		ordersPanel.setWidth(100, UNITS_PERCENTAGE);
		ordersGrid.setWidth("100%");
		ordersGrid.addStyleName(Reindeer.LAYOUT_BLACK);
		ordersPanel.addComponent(ordersGrid);
		ordersPanel.addComponent(l);
		addComponent(ordersPanel);

		/* COMPOSITION */
		numField.setValue(0);

		typeSelect.addContainerProperty("caption", String.class, "");
		typeSelect.setItemCaptionPropertyId("caption");
		typeSelect.setNullSelectionAllowed(false);
		for (Ship s : Ship.getAvailableShips()) {
			Item i = typeSelect.addItem(s);
			i.getItemProperty("caption").setValue(s.getName());
		}
		typeSelect.select(Ship.getAvailableShips().get(0));
		typeSelect.setCaption("of type");

		List<Fleet> fleets = new ArrayList<Fleet>(VaadinPA.getPlanet().fleets);
		fleets.add(0, VaadinPA.getPlanet().homeFleet);

		fromSelect.addContainerProperty("caption", String.class, "");
		fromSelect.setItemCaptionPropertyId("caption");
		fromSelect.setNullSelectionAllowed(false);
		for (Fleet f : fleets) {
			Item i = fromSelect.addItem(f);
			i.getItemProperty("caption").setValue(f.name);
		}
		fromSelect.select(fleets.get(0));
		fromSelect.setCaption("from");

		toSelect.addContainerProperty("caption", String.class, "");
		toSelect.setItemCaptionPropertyId("caption");
		toSelect.setNullSelectionAllowed(false);
		for (Fleet f : fleets) {
			Item i = toSelect.addItem(f);
			i.getItemProperty("caption").setValue(f.name);
		}
		toSelect.select(fleets.get(1));
		toSelect.setCaption("to");

		compositionGrid.setWidth("100%");
		addComponent(compositionGrid);

		l = new HorizontalLayout();
		l.addStyleName(Reindeer.LAYOUT_BLACK);

		l.addComponent(numField);
		l.addComponent(typeSelect);
		l.addComponent(fromSelect);
		l.addComponent(toSelect);

		Button move = new Button("Move", new MoveListener());
		l.addComponent(move);

		l.setSpacing(true);
		addComponent(l);

		setSpacing(true);

	}

	@Override
	public void reload() {

		super.reload();

		/* ORDERS */
		ordersGrid.removeAllComponents();

		int col = 0;
		for (Fleet f : VaadinPA.getPlanet().fleets) {
			int row = 0;
			ordersGrid.addComponent(new Label("<b>" + f.name + "</b>", Label.CONTENT_XHTML), col, row++);
			ordersGrid.addComponent(new Label("<b>Order:</b> " + f.currentOrder.toString(), Label.CONTENT_XHTML), col,
					row++);

			if (f.atPlanet(VaadinPA.getPlanet().coords)) {
				if (f.eta != 0) {
					ordersGrid.addComponent(
							new Label("<b>Location:</b> home, preparing to launch", Label.CONTENT_XHTML), col, row++);
				} else {
					ordersGrid.addComponent(new Label("<b>Location:</b> home", Label.CONTENT_XHTML), col, row++);
				}
				ordersGrid.addComponent(new Label(), col, row++);
			} else {
				String dest;
				if (f.location == null) {
					dest = "In transit to " + Universe.instance.get(getDestinationFor(f)).name + " ("
							+ getDestinationFor(f).toString() + ")";
				} else if (f.location.equals(VaadinPA.getPlanet().coords)) {
					dest = "At home";
				} else {
					dest = "At other planet: " + Universe.instance.get(f.location).name + " (" + f.location.toString()
							+ ")";
				}
				ordersGrid.addComponent(new Label("<b>Location:</b> " + dest, Label.CONTENT_XHTML), col, row++);
				ordersGrid.addComponent(new Label("<b>ETA:</b> " + getETAFor(f) + " ticks", Label.CONTENT_XHTML), col,
						row++);
			}

			col++;
		}

		destinationSelect.removeAllItems();
		for (Planet p : Universe.instance.values()) {
			if (p.equals(VaadinPA.getPlanet())) {
				continue;
			}
			Item i = destinationSelect.addItem(p);
			i.getItemProperty("caption").setValue(p.toString());
		}
		destinationSelect.select(Universe.instance.values().iterator().next());

		/* COMPOSITION */
		compositionGrid.removeAllComponents();

		List<Fleet> fleets = new ArrayList<Fleet>(VaadinPA.getPlanet().fleets);
		fleets.add(0, VaadinPA.getPlanet().homeFleet);

		compositionGrid.addComponent(new Label("Ship name"));
		for (Fleet f : fleets) {
			compositionGrid.addComponent(new Label(f.name));
		}

		for (Ship s : Ship.getAvailableShips()) {
			compositionGrid.addComponent(new Label(s.getName()));

			for (Fleet f : fleets) {
				compositionGrid.addComponent(new Label(f.get(s) + ""));
			}

		}
	}

	private Coordinate getDestinationFor(Fleet f) {
		for (FleetMoveCommand cmd : CommandHandler.getAllFleetMoveCommands()) {
			if (cmd.fleet.equals(f)) {
				return cmd.destination;
			}
		}
		return null;
	}

	private int getETAFor(Fleet f) {
		for (FleetMoveCommand cmd : CommandHandler.getAllFleetMoveCommands()) {
			if (cmd.fleet.equals(f)) {
				return cmd.fleet.eta - cmd.traveled;
			}
		}
		return 0;
	}

	private class MoveListener implements ClickListener {

		private static final long serialVersionUID = 4382518040240627807L;

		public void buttonClick(ClickEvent event) {

			int num;
			try {
				num = new Integer(numField.getValue().toString());
			} catch (NumberFormatException e) {
				return;
			}

			Ship s = (Ship) typeSelect.getValue();
			Fleet from = (Fleet) fromSelect.getValue();
			Fleet to = (Fleet) toSelect.getValue();

			if (num < 1 || from.equals(to)) {
				return;
			}

			if (!from.location.equals(to.location)) {
				NotificationUtil.warn("", "Fleets not at same coords");
				return;
			}

			int actualNum = from.get(s) < num ? from.get(s) : num;
			if (actualNum == 0) {
				return;
			}

			from.put(s, from.get(s) - actualNum);
			to.put(s, to.get(s) + actualNum);

			numField.setValue(0);
			reload();
		}

	}

	private class OrderIssueListener implements ClickListener {

		private static final long serialVersionUID = -7925808557848405476L;

		public void buttonClick(ClickEvent event) {

			Fleet f = (Fleet) fleetSelect.getValue();
			if (!f.atPlanet(VaadinPA.getPlanet().coords)) {
				NotificationUtil.notify("", "Fleet is away, can not issue orders");
				return;
			}

			if (f.isEmpty()) {
				NotificationUtil.notify("", "Fleet has no ships");
				return;
			}

			Planet destination = (Planet) destinationSelect.getValue();
			if (destination == null) {
				return;
			}

			FleetOrder order = (FleetOrder) orderSelect.getValue();

			FleetMoveCommand c = new FleetMoveCommand(VaadinPA.getPlanet(), destination, f, order);
			CommandHandler.handle(c);

			reload();

		}

	}

	@Override
	public String getTitle() {
		return "Fleet overview";
	}

	@SuppressWarnings("unchecked")
	@Override
	protected List<? extends Command> getCommands() {
		return CommandHandler.getEvents(FleetMoveCommand.class);
	}
}
